package com.chonglie;

import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import com.chonglie.tools.ImageUtils;

public class GifActivity extends Activity {

	private SurfaceView surfaceView;
	private SurfaceHolder surfaceHolder;

	private List<Integer> images;
	private List<int[]> imageSizes;
	private List<Bitmap> bitmaps;

	private Thread singleThread;

	private Thread readThread;
	private Thread drawThread;

	private static final long PIC_PER_MS = 1000 / 10;

	private static final int MAX_COUNT = 10;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.gif_view);

		images = ImageUtils.getImageList("g");
		imageSizes = ImageUtils.getImageSizes(this, images);
		bitmaps = ImageUtils.getBitmaps(this, images);

		surfaceView = (SurfaceView) findViewById(R.id.gif_view_single_thread);
		surfaceHolder = surfaceView.getHolder();

		Log.i("GifActivity.onCreate", null == surfaceHolder ? "null"
				: "not null");

	}

	@Override
	protected void onStop() {
		super.onStop();
		stopSingleThread();
		stopMultiThreads();
	}

	private void stopSingleThread() {
		if (null != singleThread) {
			singleThread.interrupt();
			singleThread = null;
		}
	}

	private void stopMultiThreads() {

		if (null != readThread) {
			readThread.interrupt();
			readThread = null;
		}

		if (null != drawThread) {
			drawThread.interrupt();
			drawThread = null;
		}
	}

	public void drawBySingleThread(View view) {

		if (null == singleThread) {
			stopMultiThreads();
			Log.i("drawBySingleThread", "start thread");
			singleThread = new LoadAndDrawThread(0, 0, images, imageSizes,
					surfaceHolder);
			singleThread.start();
		} else {
			stopSingleThread();
		}
	}

	public void drawByMultiThread(View view) {
		if (null == readThread) {
			stopSingleThread();
			BlockingQueue<Bitmap> queue = new ArrayBlockingQueue<Bitmap>(
					MAX_COUNT);

			readThread = new ReadThread(queue, MAX_COUNT, images);
			readThread.start();

			drawThread = new DrawThread(queue, 10, 10, surfaceHolder);
			drawThread.start();

		} else {
			stopMultiThreads();
		}
	}

	class MyCallback implements SurfaceHolder.Callback {

		public void surfaceDestroyed(SurfaceHolder holder) {
			Log.i("Surface", "Destroyed");
		}

		public void surfaceCreated(SurfaceHolder holder) {
			Log.i("Surface:", "Created");
		}

		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
			Log.i("Surface", "Changed");
		}
	}

	class LoadAndDrawThread extends Thread {

		private int x;
		private int y;
		private List<Integer> images;
		private List<int[]> imageSizes;
		private SurfaceHolder holder;

		public LoadAndDrawThread(int x, int y, List<Integer> images,
				List<int[]> imageSizes, SurfaceHolder surfaceHolder) {
			super();
			this.x = x;
			this.y = y;
			this.images = images;
			this.imageSizes = imageSizes;
			this.holder = surfaceHolder;
		}

		@Override
		public void run() {
			int imgIndex = 0;
			long duration = 0;
			long start;
			long end;
			long sleep;
			while (!this.isInterrupted()) {
				start = System.currentTimeMillis();

				Bitmap bmImg = bitmaps.get(imgIndex);

				Canvas c = holder.lockCanvas(new Rect(this.x, this.y, this.x
						+ imageSizes.get(imgIndex)[0], this.y
						+ imageSizes.get(imgIndex)[1]));

				if (null == c) {
					Log.i("LoadAndDrawThread", "c = null");
					break;
				}

				c.drawBitmap(bmImg, this.x, this.y, new Paint());
				imgIndex++;
				if (imgIndex == images.size())
					imgIndex = 0;

				holder.unlockCanvasAndPost(c);// ������Ļ��ʾ����

				end = System.currentTimeMillis();
				duration = end - start;

				sleep = PIC_PER_MS - duration;

				if (sleep > 0) {
					try {
						Log.i("LoadAndDrawThread", "sleep:" + sleep);
						sleep(sleep);
					} catch (InterruptedException e) {
						break;
					}
				}

			}
		}
	}

	class ReadThread extends Thread {
		private BlockingQueue<Bitmap> queue;
		private int maxSize;
		private List<Integer> images;

		public ReadThread(BlockingQueue<Bitmap> queue, int maxSize,
				List<Integer> images) {
			super();
			this.queue = queue;
			this.maxSize = maxSize;
			this.images = images;
		}

		@Override
		public void run() {

			int imgIndex = 0;
			while (!this.isInterrupted()) {
				if (queue.size() <= maxSize) {
					Log.i("ReadThread", "read " + imgIndex);

					try {
						queue.put(bitmaps.get(imgIndex));
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					imgIndex++;
					if (imgIndex == images.size())
						imgIndex = 0;
				}
			}
		}

	}

	class DrawThread extends Thread {
		private BlockingQueue<Bitmap> queue;
		private int x;
		private int y;
		private SurfaceHolder holder;

		public DrawThread(BlockingQueue<Bitmap> queue, int x, int y,
				SurfaceHolder holder) {
			super();
			this.queue = queue;
			this.x = x;
			this.y = y;
			this.holder = holder;
		}

		@Override
		public void run() {
			int imgIndex = 0;
			int imgWidth;
			int imgHeight;

			long duration = 0;
			long start;
			long end;
			long sleep;

			while (!this.isInterrupted()) {

				start = System.currentTimeMillis();
				Bitmap bitmap = null;

				if (!queue.isEmpty()) {
					try {
						bitmap = queue.take();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}

				if (bitmap != null) {
					imgWidth = bitmap.getWidth();
					imgHeight = bitmap.getHeight();

					Log.i("DrawThread",
							x + "," + y + "," + imageSizes.get(imgIndex)[0]
									+ "," + imageSizes.get(imgIndex)[1]);

					Canvas c = holder.lockCanvas(new Rect(this.x, this.y,
							this.x + imgWidth, this.y + imgHeight));

					if (null == c) {
						Log.i("DrawThread", "c = null");
						break;
					}

					c.drawBitmap(bitmap, this.x, this.y, new Paint());
					holder.unlockCanvasAndPost(c);// ������Ļ��ʾ����
				}

				end = System.currentTimeMillis();
				duration = end - start;
				sleep = PIC_PER_MS - duration;

				if (sleep > 0) {
					try {
						Log.i("LoadAndDrawThread", "sleep:" + sleep);
						sleep(sleep);
					} catch (InterruptedException e) {
						break;
					}
				}

			}

		}
	}
}
